Skip to content

Select and copy text in the viewer - #859

Merged
SimonCropp merged 3 commits into
mainfrom
viewer-text-selection
Aug 31, 2026
Merged

Select and copy text in the viewer#859
SimonCropp merged 3 commits into
mainfrom
viewer-text-selection

Conversation

@SimonCropp

Copy link
Copy Markdown
Member

Every pane was owner drawn with no selection anywhere in the model, so the one thing a reader wants to do with a failing snapshot — take the text somewhere else — could not be done at all.

Drag across either pane to select, ctrl+c to copy, ctrl+a to select one side. Every entry's context menu also offers Copy selection, and a Copy item per pane that has anything in it — a pending delete's left side is the state after accepting, which is no file, so it gets no item rather than one that reports having copied nothing.

A drag arrives from a head as both of its ends at once, reported on every frame the button is held rather than as press, move and release events. The managed side is already holding the selection by then, so a release has nothing to add, and a whole press-drag-release landing inside one frame still arrives whole. Rows are rows of the whole side rather than of the visible slice, because a head knows the scroll top it drew the press with and is the only thing that can resolve a drag spanning a wheel notch.

A selection names the entry it was dragged in, so one left behind by an accept, a discard or a variant cycle stops existing rather than needing a clear on every transition — one of which would eventually be missed.

AsciiRenderer draws a fixed width character grid and has no way to invert part of a line without changing its width. So what the model universally states about a selection goes in the status line, where every renderer draws it and the text snapshots show it, and the highlight is the enrichment the three pixel heads paint on top. The same bargain ImagePane already makes.

Copying is IViewerWindow.SetClipboard rather than a ViewerActions member, because a clipboard belongs to a toolkit the way a window does: WinForms, AppKit and GLFW each own one, and the alternative was shelling out to clip, pbcopy and whichever of xclip or wl-copy happened to be installed. It is answered before the owner link, since the text is already in this process and an owner's answer would be a round trip to fetch what this one is holding.

Keys.A was matched ignoring modifiers in all three heads, so ctrl+a would have accepted the snapshot rather than selecting it.

ABI

DEVIEW_VERSION goes to 8: DeviewRow carries the selected run of its text and DeviewInput reports a drag across a pane, with deview_set_clipboard beside them. DeviewRow is a widened array element, so this is the same kind of bump 6 was. The rebuilt binaries are already on this branch, from #858. The missing note for 7 is backfilled while here.

One expected failure

PixelTests.Selection is new and has no Linux or macOS baseline yet. Both pixel jobs will fail on it and upload the images as received-* artifacts, which is where those two baselines come from.

WindowsPixelTests.Selection is committed, and PaneHitTests closes the loop the other way: it draws a selection, finds the pixels it landed on and feeds them back through the hit test. That is the only check that the painter and the hit test are reading one layout — the pixel snapshots show where a highlight went and say nothing about where a click resolves to.

SimonCropp and others added 3 commits August 31, 2026 12:08
Every pane was owner drawn with no selection anywhere in the model, so the one
thing a reader wants to do with a failing snapshot - take the text somewhere
else - could not be done at all.

Drag across either pane to select, ctrl+c to copy, ctrl+a to select one side.
Every entry's context menu also offers Copy selection, and a Copy item per pane
that has anything in it. A drag arrives from a head as both of its ends at once,
reported on every frame the button is held rather than as press, move and
release events: the managed side already holds the selection by then, so a
release has nothing to add, and a whole press-drag-release landing inside one
frame still arrives whole. Rows are rows of the whole side rather than of the
visible slice, because a head knows the scroll top it drew the press with and is
the only thing that can resolve a drag spanning a wheel notch.

A selection names the entry it was dragged in, so one left behind by an accept,
a discard or a variant cycle stops existing rather than needing a clear on every
transition - one of which would eventually be missed.

AsciiRenderer draws a fixed width character grid and has no way to invert part of
a line without changing its width, so what the model universally states about a
selection goes in the status line, where every renderer draws it and the text
snapshots show it, and the highlight is the enrichment the three pixel heads
paint on top. The same bargain ImagePane already makes.

Copying is IViewerWindow.SetClipboard rather than a ViewerActions member, because
a clipboard belongs to a toolkit the way a window does: WinForms, AppKit and GLFW
each own one, and the alternative was shelling out to clip, pbcopy and whichever
of xclip or wl-copy happened to be installed. It is answered before the owner
link, since the text is already in this process and an owner's answer would be a
round trip to fetch what this one is holding.

Keys.A was matched ignoring modifiers in all three heads, so ctrl+a would have
accepted the snapshot rather than selecting it.

DEVIEW_VERSION goes to 8: DeviewRow carries the selected run and DeviewInput the
drag, with deview_set_clipboard beside them. DeviewRow is a widened array
element, so this is the same kind of bump 6 was and the binaries have to be
rebuilt with it. The missing note for 7 is backfilled while here.

PixelTests.Selection has no Linux or macOS baseline yet; those come out of the
pixel job's received artifacts once the rebuilt binaries land.
Co-authored-by: SimonCropp <122666+SimonCropp@users.noreply.github.com>
The two Selection captures are new, and the Linux context menu grew the two copy
items the ASCII snapshot and the WinForms one already show. All three came out of
the pixel jobs' received artifacts, which is where a baseline for a renderer this
machine cannot run has to come from.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant